package org.cybzacg.encryption.listener.impl;

import org.cybzacg.encryption.listener.EncryptionListener;
import org.cybzacg.encryption.context.EncryptionContext;
import org.cybzacg.encryption.model.EncryptionResult;
import org.cybzacg.encryption.enums.EncryptionAlgorithm;
import org.cybzacg.encryption.enums.EncryptionStatus;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 日志监听器实现
 * 记录加密操作的详细日志信息
 * 
 * @author encryption team
 * @version 1.0
 */
public class LoggingListener implements EncryptionListener {
    
    private final AtomicLong encryptionCount = new AtomicLong(0);
    private final AtomicLong decryptionCount = new AtomicLong(0);
    private final AtomicLong validationCount = new AtomicLong(0);
    private final AtomicLong errorCount = new AtomicLong(0);
    private final AtomicLong warningCount = new AtomicLong(0);
    
    private final boolean enableDetailedLogging;
    private final boolean enablePerformanceLogging;
    private final DateTimeFormatter timestampFormatter;
    
    /**
     * 构造函数（默认配置）
     */
    public LoggingListener() {
        this(true, true);
    }
    
    /**
     * 构造函数
     * 
     * @param enableDetailedLogging 是否启用详细日志
     * @param enablePerformanceLogging 是否启用性能日志
     */
    public LoggingListener(boolean enableDetailedLogging, boolean enablePerformanceLogging) {
        this.enableDetailedLogging = enableDetailedLogging;
        this.enablePerformanceLogging = enablePerformanceLogging;
        this.timestampFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
    }
    
    @Override
    public void onEncryptionStart(EncryptionContext context) {
        encryptionCount.incrementAndGet();
        
        if (enableDetailedLogging) {
            logInfo("ENCRYPTION_START", formatContextInfo(context));
        }
    }
    
    @Override
    public void onEncryptionSuccess(EncryptionResult result, EncryptionContext context) {
        if (enableDetailedLogging) {
            String message = String.format("ENCRYPTION_SUCCESS - Algorithm: %s, Size: %d bytes, Time: %dms",
                context.getAlgorithm(),
                result.getData() != null ? result.getData().length : 0,
                result.getProcessingTime());
            
            logInfo("ENCRYPTION_SUCCESS", message);
        }
        
        if (enablePerformanceLogging && result.getProcessingTime() > 1000) {
            logWarning("PERFORMANCE_WARNING", 
                String.format("Encryption took %dms for algorithm %s", 
                    result.getProcessingTime(), context.getAlgorithm()));
        }
    }
    
    @Override
    public void onEncryptionFailure(Exception exception, EncryptionContext context) {
        errorCount.incrementAndGet();
        
        String message = String.format("ENCRYPTION_FAILURE - Algorithm: %s, Error: %s",
            context.getAlgorithm(),
            exception.getMessage());
        
        logError("ENCRYPTION_FAILURE", message);
        
        if (enableDetailedLogging) {
            logDebug("ENCRYPTION_FAILURE_DETAIL", formatExceptionInfo(exception));
        }
    }
    
    @Override
    public void onDecryptionStart(EncryptionContext context) {
        decryptionCount.incrementAndGet();
        
        if (enableDetailedLogging) {
            logInfo("DECRYPTION_START", formatContextInfo(context));
        }
    }
    
    @Override
    public void onDecryptionSuccess(EncryptionResult result, EncryptionContext context) {
        if (enableDetailedLogging) {
            String message = String.format("DECRYPTION_SUCCESS - Algorithm: %s, Size: %d bytes, Time: %dms",
                context.getAlgorithm(),
                result.getData() != null ? result.getData().length : 0,
                result.getProcessingTime());
            
            logInfo("DECRYPTION_SUCCESS", message);
        }
        
        if (enablePerformanceLogging && result.getProcessingTime() > 1000) {
            logWarning("PERFORMANCE_WARNING", 
                String.format("Decryption took %dms for algorithm %s", 
                    result.getProcessingTime(), context.getAlgorithm()));
        }
    }
    
    @Override
    public void onDecryptionFailure(Exception exception, EncryptionContext context) {
        errorCount.incrementAndGet();
        
        String message = String.format("DECRYPTION_FAILURE - Algorithm: %s, Error: %s",
            context.getAlgorithm(),
            exception.getMessage());
        
        logError("DECRYPTION_FAILURE", message);
        
        if (enableDetailedLogging) {
            logDebug("DECRYPTION_FAILURE_DETAIL", formatExceptionInfo(exception));
        }
    }
    
    @Override
    public void onValidationStart(EncryptionContext context) {
        validationCount.incrementAndGet();
        
        if (enableDetailedLogging) {
            logInfo("VALIDATION_START", formatContextInfo(context));
        }
    }
    
    @Override
    public void onValidationSuccess(EncryptionContext context) {
        if (enableDetailedLogging) {
            logInfo("VALIDATION_SUCCESS", "Algorithm: " + context.getAlgorithm());
        }
    }
    
    @Override
    public void onValidationFailure(Exception exception, EncryptionContext context) {
        errorCount.incrementAndGet();
        
        String message = String.format("VALIDATION_FAILURE - Algorithm: %s, Error: %s",
            context.getAlgorithm(),
            exception.getMessage());
        
        logError("VALIDATION_FAILURE", message);
        
        if (enableDetailedLogging) {
            logDebug("VALIDATION_FAILURE_DETAIL", formatExceptionInfo(exception));
        }
    }
    
    @Override
    public void onPerformanceWarning(long processingTime, EncryptionContext context) {
        warningCount.incrementAndGet();
        
        String message = String.format("PERFORMANCE_WARNING - Processing time: %dms, Algorithm: %s",
            processingTime, context != null ? context.getAlgorithm() : "Unknown");
        
        logWarning("PERFORMANCE_WARNING", message);
    }
    
    @Override
    public void onSecurityWarning(String message, EncryptionContext context) {
        warningCount.incrementAndGet();
        
        String fullMessage = String.format("SECURITY_WARNING - Algorithm: %s, Message: %s",
            context.getAlgorithm(), message);
        
        logWarning("SECURITY_WARNING", fullMessage);
    }
    
    @Override
    public void onBatchStart(int batchSize, EncryptionContext context) {
        if (enableDetailedLogging) {
            logInfo("BATCH_START", String.format("Batch size: %d, Algorithm: %s", 
                batchSize, context.getAlgorithm()));
        }
    }
    
    @Override
    public void onBatchComplete(int batchSize, int successCount, int failureCount, EncryptionContext context) {
        if (enableDetailedLogging) {
            String message = String.format("Batch completed - Size: %d, Success: %d, Failures: %d, Algorithm: %s",
                batchSize, successCount, failureCount, context.getAlgorithm());
            
            logInfo("BATCH_COMPLETE", message);
        }
    }
    
    @Override
    public void onCacheHit(EncryptionContext context) {
        if (enableDetailedLogging) {
            logInfo("CACHE_HIT", "Algorithm: " + context.getAlgorithm());
        }
    }
    
    @Override
    public void onCacheMiss(EncryptionContext context) {
        if (enableDetailedLogging) {
            logInfo("CACHE_MISS", "Algorithm: " + context.getAlgorithm());
        }
    }
    
    @Override
    public String getName() {
        return "LoggingListener";
    }
    
    @Override
    public int getPriority() {
        return 100; // 默认优先级
    }
    
    /**
     * 获取加密操作次数
     * 
     * @return 加密操作次数
     */
    public long getEncryptionCount() {
        return encryptionCount.get();
    }
    
    /**
     * 获取解密操作次数
     * 
     * @return 解密操作次数
     */
    public long getDecryptionCount() {
        return decryptionCount.get();
    }
    
    /**
     * 获取验证操作次数
     * 
     * @return 验证操作次数
     */
    public long getValidationCount() {
        return validationCount.get();
    }
    
    /**
     * 获取错误次数
     * 
     * @return 错误次数
     */
    public long getErrorCount() {
        return errorCount.get();
    }
    
    /**
     * 获取警告次数
     * 
     * @return 警告次数
     */
    public long getWarningCount() {
        return warningCount.get();
    }
    
    /**
     * 重置统计信息
     */
    public void resetStatistics() {
        encryptionCount.set(0);
        decryptionCount.set(0);
        validationCount.set(0);
        errorCount.set(0);
        warningCount.set(0);
    }
    
    /**
     * 获取统计信息摘要
     * 
     * @return 统计信息摘要
     */
    public String getStatisticsSummary() {
        return String.format(
            "EncryptionListener Statistics - Encryptions: %d, Decryptions: %d, Validations: %d, Errors: %d, Warnings: %d",
            getEncryptionCount(),
            getDecryptionCount(),
            getValidationCount(),
            getErrorCount(),
            getWarningCount()
        );
    }
    
    /**
     * 格式化上下文信息
     */
    private String formatContextInfo(EncryptionContext context) {
        if (context == null) {
            return "Context: null";
        }
        
        return String.format("Algorithm: %s, Type: %s, Timeout: %dms, BatchMode: %s",
            context.getAlgorithm(),
            context.getEncryptionType(),
            context.getTimeout(),
            context.isBatchMode());
    }
    
    /**
     * 格式化异常信息
     */
    private String formatExceptionInfo(Exception exception) {
        if (exception == null) {
            return "Exception: null";
        }
        
        StringBuilder sb = new StringBuilder();
        sb.append("Exception: ").append(exception.getClass().getSimpleName());
        sb.append(", Message: ").append(exception.getMessage());
        
        if (exception.getCause() != null) {
            sb.append(", Cause: ").append(exception.getCause().getMessage());
        }
        
        return sb.toString();
    }
    
    /**
     * 记录信息日志
     */
    private void logInfo(String level, String message) {
        System.out.println(formatLogMessage("INFO", level, message));
    }
    
    /**
     * 记录警告日志
     */
    private void logWarning(String level, String message) {
        System.out.println(formatLogMessage("WARN", level, message));
    }
    
    /**
     * 记录错误日志
     */
    private void logError(String level, String message) {
        System.err.println(formatLogMessage("ERROR", level, message));
    }
    
    /**
     * 记录调试日志
     */
    private void logDebug(String level, String message) {
        System.out.println(formatLogMessage("DEBUG", level, message));
    }
    
    /**
     * 格式化日志消息
     */
    private String formatLogMessage(String level, String event, String message) {
        String timestamp = LocalDateTime.now().format(timestampFormatter);
        return String.format("[%s] [%s] [%s] %s", timestamp, level, event, message);
    }
}
